package com.luhuiguo.cms.server.web.filter;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GenericResponseWrapper extends HttpServletResponseWrapper implements Serializable {

    private static final long serialVersionUID = -2289753145389766757L;

    private static final Logger logger = LoggerFactory.getLogger(GenericResponseWrapper.class);

    private int statusCode = SC_OK;
    private int contentLength;
    private String contentType;
    private final List<String[]> headers = new ArrayList<String[]>();
    private final List<Cookie> cookies = new ArrayList<Cookie>();
    private ServletOutputStream outstr;
    private PrintWriter writer;

    /**
     * Creates a GenericResponseWrapper
     */
    public GenericResponseWrapper(final HttpServletResponse response, final OutputStream outstr) {
        super(response);
        this.outstr = new FilterServletOutputStream(outstr);
    }

    /**
     * Gets the outputstream.
     */
    public ServletOutputStream getOutputStream() {
        return outstr;
    }

    /**
     * Sets the status code for this response.
     */
    public void setStatus(final int code) {
        statusCode = code;
        super.setStatus(code);
    }

    /**
     * Send the error. If the response is not ok, most of the logic is bypassed
     * and the error is sent raw Also, the content is not cached.
     * 
     * @param i
     *            the status code
     * @param string
     *            the error message
     * @throws IOException
     */
    public void sendError(int i, String string) throws IOException {
        statusCode = i;
        super.sendError(i, string);
    }

    /**
     * Send the error. If the response is not ok, most of the logic is bypassed
     * and the error is sent raw Also, the content is not cached.
     * 
     * @param i
     *            the status code
     * @throws IOException
     */
    @Override
    public void sendError(int i) throws IOException {
        statusCode = i;
        super.sendError(i);
    }

    /**
     * Send the redirect. If the response is not ok, most of the logic is
     * bypassed and the error is sent raw. Also, the content is not cached.
     * 
     * @param string
     *            the URL to redirect to
     * @throws IOException
     */
    @Override
    public void sendRedirect(String string) throws IOException {
        statusCode = HttpServletResponse.SC_MOVED_TEMPORARILY;
        super.sendRedirect(string);
    }

    /**
     * Sets the status code for this response.
     */
    @Override
    public void setStatus(final int code, final String msg) {
        statusCode = code;
        logger.warn("Discarding message because this method is deprecated.");
        super.setStatus(code);
    }

    /**
     * Returns the status code for this response.
     */

    public int getStatus() {
        return statusCode;
    }

    /**
     * Sets the content length.
     */
    @Override
    public void setContentLength(final int length) {
        this.contentLength = length;
        super.setContentLength(length);
    }

    /**
     * Gets the content length.
     */

    public int getContentLength() {
        return contentLength;
    }

    /**
     * Sets the content type.
     */
    @Override
    public void setContentType(final String type) {
        this.contentType = type;
        super.setContentType(type);
    }

    /**
     * Gets the content type.
     */
    @Override
    public String getContentType() {
        return contentType;
    }

    /**
     * Gets the print writer.
     */
    @Override
    public PrintWriter getWriter() throws IOException {
        if (writer == null) {
            writer = new PrintWriter(new OutputStreamWriter(outstr, getCharacterEncoding()), true);
        }
        return writer;
    }

    /**
     * Adds a header.
     */
    @Override
    public void addHeader(final String name, final String value) {
        final String[] header = new String[]{ name, value };
        headers.add(header);
        super.addHeader(name, value);
    }

    /**
     * @see #addHeader
     */
    @Override
    public void setHeader(final String name, final String value) {
        addHeader(name, value);
    }

    /**
     * Gets the headers.
     */

    public List<String[]> getHeaders() {
        return headers;
    }

    /**
     * Adds a cookie.
     */
    @Override
    public void addCookie(final Cookie cookie) {
        cookies.add(cookie);
        super.addCookie(cookie);
    }

    /**
     * Gets all the cookies.
     */

    public List<Cookie> getCookies() {
        return cookies;
    }

    /**
     * Flushes buffer and commits response to client.
     */
    @Override
    public void flushBuffer() throws IOException {
        flush();
        super.flushBuffer();
    }

    /**
     * Resets the response.
     */
    @Override
    public void reset() {
        super.reset();
        cookies.clear();
        headers.clear();
        statusCode = SC_OK;
        contentType = null;
        contentLength = 0;
    }

    /**
     * Resets the buffers.
     */
    @Override
    public void resetBuffer() {
        super.resetBuffer();
    }

    /**
     * Flushes all the streams for this response.
     */

    public void flush() throws IOException {
        if (writer != null) {
            writer.flush();
        }
        outstr.flush();
    }
}
